package me.boot.db.mybatis.propertites;


import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.handler.TableNameHandler;
import com.google.common.collect.Maps;
import lombok.Data;
import lombok.Getter;
import me.base.utils.ReflectUtil;
import me.boot.common.constant.DbConst;
import me.boot.db.mybatis.interceptor.tenant.TenantDatasource;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.NestedConfigurationProperty;

import java.util.Collections;
import java.util.List;
import java.util.Map;

import static me.boot.common.constant.DbConst.COLUMN_TENANT_ID;
import static me.boot.common.constant.DbConst.TENANT_TABLE_NAME;

@Getter
@ConfigurationProperties(prefix = DbProperties.PREFIX)
public class DbProperties {
    public final static String PREFIX = "db";

    @NestedConfigurationProperty
    private Tenant tenant = new Tenant();

    @NestedConfigurationProperty
    private DynamicTable dynamicTable = new DynamicTable();

    @NestedConfigurationProperty
    private Transaction transaction = new Transaction();

    @NestedConfigurationProperty
    private ForeignKey foreignKey = new ForeignKey();


    /**
     * 默认数据库是mysql
     */
    private DbType dbType = DbType.MYSQL;

    /**
     * 分页大小限制
     */
    private long pageMaxLimit = DbConst.PAGE_MAX_LIMIT;


    /**
     * 是否启用 乐观锁插件
     */
    private boolean optimisticLocker = true;

    /**
     * 是否启用 防止全表更新与删除插件
     */
    private boolean blockAttack = false;

    /**
     * 是否启用  sql性能规范插件
     */
    private boolean illegalSql = false;

    /**
     * 是否启用数据权限
     */
    private boolean dataScope = false;

    @Data
    public static class ForeignKey {

        /**
         * 是否启用 外键检查插件
         */
        private boolean enable = true;


        /**
         * 实体所在包名（外键插件需要扫描实体模型）
         */
        private List<String> entityPackages;

    }

    /**
     * 租户属性
     */
    @Data
    public static class Tenant {
        /**
         * 多租户模式
         */
        private TenantMode mode = TenantMode.NONE;

        private String tenantTable = TENANT_TABLE_NAME;

        /**
         * COLUMN 模式的默认配置
         */
        @NestedConfigurationProperty
        private Column column = new Column();

        /**
         * SCHEMA 模式的默认配置
         */
        @NestedConfigurationProperty
        private Schema schema = new Schema();

        /**
         * DATASOURCE 模式的默认配置
         */
        @NestedConfigurationProperty
        private Datasource datasource = new Datasource();

        @Data
        public static class Column {

            /**
             * 多租户字段名称
             */
            private String tenantColumn = COLUMN_TENANT_ID;

            /**
             * 不含租户字段的表
             */
            private List<String> ignoreTables = Collections.singletonList(
                    TENANT_TABLE_NAME
            );
        }

        @Data
        public static class Schema {

            /**
             * 租户库 前缀
             */
            private String tenantPrefix = DbConst.TENANT_SCHEMA_PREFIX;

            /**
             * 不在租户schema存储的表， 如租户表
             */
            private List<String> ignoreTables = Collections.singletonList(
                    TENANT_TABLE_NAME
            );
        }

        @Data
        public static class Datasource {

            /**
             * 租户数据源配置的存储方式
             * <p>
             * Style.Table
             * </p>
             */
            private Style style = Style.Column;

            public enum Style {

                /**
                 * 独立表存储
                 * <p>
                 * 表定义参见 {@link TenantDatasource} 类
                 * url、username、password 不可缺
                 * </p>
                 */
                Table,

                /**
                 * 租户表的单独字段存储
                 * <p>
                 * 存储表约定 {@link TENANT_TABLE_NAME}
                 * json字符格式，结构参见 {@link TenantDatasource} 类
                 * </p>
                 */
                Column
            }
        }
    }


    /**
     * 动态表配置
     */
    @Data
    public static class DynamicTable {
        /**
         * 是否启用 动态表名插件
         */
        private boolean enable = true;
        /**
         * 是否自动创建动态表
         */
        private boolean autoCreateTable = true;
        /**
         * 表名与handler对应表
         * key    -- 表名
         * value  --  TableNameHandler实现类
         */
        private Map<String, String> tables = Maps.newHashMap();

        public TableNameHandler getHandlerByTable(String table) {
            return tables.containsKey(table) ? fromClass(tables.get(table)) : null;
        }

        private TableNameHandler fromClass(String classFullName) {
            return ReflectUtil.toInstance(classFullName);
        }
    }

    @Data
    public static class Transaction {

//        /**
//         * 是否启用 seata
//         */
//        private boolean seata = false;
//
//        /**
//         * 事务扫描基础包
//         */
//        private String transactionScanPackage = "me.boot";
//
//        /**
//         * 事务超时时间
//         */
//        private int txTimeout = 60 * 60;
//
//        /**
//         * 统一管理事务的方法名
//         */
//        private List<String> transactionAttributeList = new ArrayList<>(Arrays.asList("add*", "save*", "insert*",
//                "create*", "update*", "edit*", "upload*", "delete*", "remove*",
//                "clean*", "recycle*", "batch*", "mark*", "disable*", "enable*", "handle*", "syn*",
//                "reg*", "gen*", "*Tx"
//        ));

    }

}


